package cn.mw.cmdb.viewProcessor;

import cn.mw.cmdb.entity.*;
import cn.mw.cmdb.param.ModelPropertyParam;
import cn.mw.cmdb.param.MwRoomLayoutBaseInfo;
import cn.mw.cmdb.param.MwRoomLayoutDataBaseParam;
import cn.mw.cmdb.param.MwUpdateInstanceCheckInfoParam;
import cn.mw.cmdb.processor.ModelViewTypeContext;
import cn.mw.cmdb.processor.ModelViewTypeProccessor;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.InstanceServiceImpl;
import cn.mw.cmdb.service.impl.ModelPropertyServiceImpl;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.base.Strings;
import org.apache.commons.collections.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static cn.mw.cmdb.entity.ModelInfo.prefix;
import static cn.mw.cmdb.entity.PropertyTypeEnumSingle.defaultValueKey;
import static cn.mw.cmdb.entity.PropertyTypeEnumSingle.enumInfoListKey;
import static cn.mw.cmdb.util.ValConvertUtil.intValueConvert;
import static cn.mw.cmdb.viewProcessor.ModelViewCabinetProcess.getCabinetPropertyIds;
import static cn.mw.cmdb.viewProcessor.ModelViewUNumProcess.getUNumTypePropertyIds;

public class ModelViewRoomProcess implements ModelViewTypeProccessor {
    private static String rowNum = prefix + "rowNum";
    private static String colNum = prefix + "colNum";
    public static String roomCode = prefix + "roomCode";
    public static String layoutDataRoom = prefix +  "layoutDataRoom";
    private static String XAxisCode =prefix +  "XAxisCode";
    private static String YAxisCode =prefix + "YAxisCode";
    private static String rowNumKey = "行数";
    private static String colNumKey = "列数";
    private static String layoutKey = "布局样式";
    private static String roomCodeKey = "机房编码";
    private static String XAxisCodeKey = "编号(X轴)";
    private static String YAxisCodeKey = "编号(Y轴)";
    private static String roomCatologName = "机房布局";
    private static String enumInfoValNum = "数字";
    private static String enumInfoValLetter = "字母";

    @Override
    public Object genModelViewProperty(ModelViewTypeContext context) throws Exception {
        if (context != null && context.getParam() != null && (context.getParam() instanceof ModelInfo)) {
            ModelInfo param = (ModelInfo) context.getParam();
            Map<String, PropertyInfo> properties = param.getProperties();

            CmdbServiceManage cmdbServiceManage = context.getCmdbServiceManage();
            ModelPropertyServiceImpl service = (ModelPropertyServiceImpl) cmdbServiceManage.getModelService(ModelPropertyServiceImpl.ID);
            //清除其他视图对应的字段
            ModelPropertyParam propertyParam = editorModelPropertyField(param);
            service.doRemove(propertyParam);

            //内置机房模型字段，新增机房模型时，自动生成
            PropertyInfo propertyInfo = new PropertyInfo();
            propertyInfo.setModelId(param.getId());
            propertyInfo.setName(rowNumKey);
            propertyInfo.setEnableShow(true);
            propertyInfo.setDefaultListVisible(true);
            propertyInfo.setPropertyCatologName(roomCatologName);
            PropertyTypeRef typeRef = new PropertyTypeRef();
            typeRef.setTypeId(PropertyTypeInt.ID);
            propertyInfo.setPropertyTypeRef(typeRef);
            propertyInfo.setFieldViewAuthTypes(Set.of(FieldViewAuthType.add, FieldViewAuthType.upd, FieldViewAuthType.sel, FieldViewAuthType.list));
            propertyInfo.setSortNum(1);
            propertyInfo.setId(rowNum);
            properties.put(propertyInfo.getId(), propertyInfo);

            propertyInfo = new PropertyInfo();
            propertyInfo.setModelId(param.getId());
            propertyInfo.setName(colNumKey);
            propertyInfo.setEnableShow(true);
            propertyInfo.setDefaultListVisible(true);
            propertyInfo.setPropertyCatologName(roomCatologName);
            typeRef = new PropertyTypeRef();
            typeRef.setTypeId(PropertyTypeInt.ID);
            propertyInfo.setPropertyTypeRef(typeRef);
            propertyInfo.setFieldViewAuthTypes(Set.of(FieldViewAuthType.add, FieldViewAuthType.upd, FieldViewAuthType.sel, FieldViewAuthType.list));
            propertyInfo.setId(colNum);
            propertyInfo.setSortNum(2);
            properties.put(propertyInfo.getId(), propertyInfo);

            propertyInfo = new PropertyInfo();
            propertyInfo.setModelId(param.getId());
            propertyInfo.setName(roomCodeKey);
            propertyInfo.setEnableShow(true);
            propertyInfo.setDefaultListVisible(true);
            propertyInfo.setPropertyCatologName(roomCatologName);
            typeRef = new PropertyTypeRef();
            typeRef.setTypeId(PropertyTypeString.ID);
            propertyInfo.setPropertyTypeRef(typeRef);
            propertyInfo.setFieldViewAuthTypes(Set.of(FieldViewAuthType.add, FieldViewAuthType.upd, FieldViewAuthType.sel, FieldViewAuthType.list));
            propertyInfo.setId(roomCode);
            propertyInfo.setSortNum(2);
            properties.put(propertyInfo.getId(), propertyInfo);

            propertyInfo = new PropertyInfo();
            propertyInfo.setModelId(param.getId());
            propertyInfo.setName(XAxisCodeKey);
            propertyInfo.setEnableShow(false);
            propertyInfo.setDefaultListVisible(false);
            propertyInfo.setPropertyCatologName(roomCatologName);
            typeRef = new PropertyTypeRef();
            typeRef.setTypeId(PropertyTypeEnumSingle.ID);
            Map contextMap = new HashMap();
            contextMap.put(enumInfoListKey, Arrays.asList(enumInfoValNum, enumInfoValLetter));
            contextMap.put(defaultValueKey, enumInfoValNum);
            typeRef.setContext(contextMap);
            propertyInfo.setPropertyTypeRef(typeRef);
            propertyInfo.setFieldViewAuthTypes(Set.of(FieldViewAuthType.add, FieldViewAuthType.upd));
            propertyInfo.setId(XAxisCode);
            propertyInfo.setSortNum(3);
            properties.put(propertyInfo.getId(), propertyInfo);

            propertyInfo = new PropertyInfo();
            propertyInfo.setModelId(param.getId());
            propertyInfo.setName(YAxisCodeKey);
            propertyInfo.setEnableShow(false);
            propertyInfo.setDefaultListVisible(false);
            propertyInfo.setPropertyCatologName(roomCatologName);
            typeRef = new PropertyTypeRef();
            typeRef.setTypeId(PropertyTypeEnumSingle.ID);
            contextMap = new HashMap();
            contextMap.put(enumInfoListKey, Arrays.asList(enumInfoValNum, enumInfoValLetter));
            contextMap.put(defaultValueKey, enumInfoValLetter);
            typeRef.setContext(contextMap);
            propertyInfo.setPropertyTypeRef(typeRef);
            propertyInfo.setFieldViewAuthTypes(Set.of(FieldViewAuthType.add, FieldViewAuthType.upd));
            propertyInfo.setId(YAxisCode);
            propertyInfo.setSortNum(4);
            properties.put(propertyInfo.getId(), propertyInfo);

            propertyInfo = new PropertyInfo();
            propertyInfo.setModelId(param.getId());
            propertyInfo.setName(layoutKey);
            propertyInfo.setEnableShow(true);
            propertyInfo.setDefaultListVisible(true);
            propertyInfo.setPropertyCatologName(roomCatologName);
            typeRef = new PropertyTypeRef();
            typeRef.setTypeId(PropertyTypeLayoutRoom.ID);
            propertyInfo.setPropertyTypeRef(typeRef);
            propertyInfo.setFieldViewAuthTypes(Set.of(FieldViewAuthType.add, FieldViewAuthType.upd, FieldViewAuthType.sel, FieldViewAuthType.list));
            propertyInfo.setId(layoutDataRoom);
            propertyInfo.setSortNum(5);
            properties.put(propertyInfo.getId(), propertyInfo);

        }
        return null;
    }


    /**
     * 清除U位管理视图对应的字段
     */
    public static ModelPropertyParam editorModelPropertyField(ModelInfo param) {
        ModelPropertyParam propertyParam = new ModelPropertyParam();
        Set<String> ids = new HashSet<>();
        getCabinetPropertyIds(ids);
        getUNumTypePropertyIds(ids);

        propertyParam.setIds(new ArrayList<>(ids));
        propertyParam.setModelId(param.getId());
        return propertyParam;
    }

    public static Set<String> getRoomPropertyIds(Set<String> ids) {
        ids.add(rowNum);
        ids.add(colNum);
        ids.add(roomCode);
        ids.add(XAxisCode);
        ids.add(YAxisCode);
        ids.add(layoutDataRoom);
        return ids;
    }


    @Override
    public Object addInstanceHandle(ModelViewTypeContext context) throws Exception {
        return null;
    }

    @Override
    public Object updInstanceHandle(ModelViewTypeContext context) throws Exception {
        //获取修改后提交的实例数据
        List<InstanceInfo> newList = (List<InstanceInfo>) context.getParam();
        CmdbServiceManage cmdbServiceManage = context.getCmdbServiceManage();
        InstanceServiceImpl modelService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        List<String> instanceId = newList.stream().map(s -> s.getId()).collect(Collectors.toList());
        //获取数据库中原始实例数据
        List<InstanceInfo> oldList = modelService.doListByIdsNotAuth(instanceId);
        //根据机房id获取对应的整合之后布局数据
        Map<String, Map<String, InstanceInfo>> ms = modelService.getCabinetPositionByRoomId(instanceId);
        MwUpdateInstanceCheckInfoParam checkInfoParam = new MwUpdateInstanceCheckInfoParam();
        List<InstanceInfo> disList = new ArrayList<>();
        String message = "";
        for (InstanceInfo instanceInfo : newList) {
            String roomId = instanceInfo.getId();
            List<Integer> xList = new ArrayList<>();
            List<Integer> yList = new ArrayList<>();
            if (ms != null && ms.containsKey(roomId)) {
                //获取机柜占用坐标信息
                Map<String, InstanceInfo> positionMap = ms.get(roomId);
                positionMap.forEach((k, v) -> {
                    String positionStr = k;
                    InstanceInfo cabinetInfo = v;
                    int XPosition = 0;
                    int YPosition = 0;
                    if (!Strings.isNullOrEmpty(positionStr) && positionStr.contains(",")) {
                        String[] split = positionStr.split(",");
                        XPosition = intValueConvert(split[0]);
                        YPosition = intValueConvert(split[1]);
                        xList.add(XPosition);
                        yList.add(YPosition);
                    }
                });
            }
            //获取机柜占位的最大X轴坐标
            int xNum = Collections.max(xList);
            //获取机柜占位的最大Y轴坐标
            int yNum = Collections.max(yList);

            if (instanceInfo.getData() != null && instanceInfo.getData().get(layoutDataRoom) != null) {
                Object layoutData = instanceInfo.getData().get(layoutDataRoom);
                //获取机房布局数据
                MwRoomLayoutDataBaseParam mwRoomLayoutDataBaseParam = JSONObject.parseObject(JSONObject.toJSONString(layoutData), MwRoomLayoutDataBaseParam.class);
                List<List<MwRoomLayoutBaseInfo>> layoutDataBase = mwRoomLayoutDataBaseParam.getLayoutData();
                if (CollectionUtils.isNotEmpty(layoutDataBase)) {
                    //修改后的机房的实际X轴大小
                    int XSize = layoutDataBase.size();
                    //修改后的机房的实际Y轴大小
                    int ySize = layoutDataBase.get(0).size();
                    //机房布局位置小于机柜所在的位置,改条布局数据不能修改
                    if (XSize < xNum || ySize < yNum) {
                        String s = "";
                        if (XSize < xNum) {
                            s += "第" + xNum + "行";
                        }
                        if (ySize < yNum) {
                            s += "第" + xNum + "列";
                        }
                        message += instanceInfo.getInstanceName() + "布局修改失败;" + s + "已有机柜占用";
                        continue;
                    }
                }
                instanceInfo.getData().put(layoutDataRoom, mwRoomLayoutDataBaseParam);
                disList.add(instanceInfo);
            }

        }
        checkInfoParam.setMessage(message);
        checkInfoParam.setInstanceInfoList(disList);
        return checkInfoParam;
    }
}
